package com.xzy.learn.spring.lookup;

import com.xzy.learn.spring.entity.User;
import com.xzy.learn.spring.lookup.config.ChildBeanFactoryConfig;
import com.xzy.learn.spring.lookup.config.ParentBeanFactoryConfig;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Map;

/**
 * 层次性的依赖查找
 *
 * @author xzy.xiao
 * @date 2022/6/6  15:50
 */
public class HierarchicalLookupDemo {
    public static void main(String[] args) {
//        findByName();
        findByType();
    }

    /*-------------------------层次性查找：根据 Bean 类型查找实例列表-------------------*/

    public static void findByType() {
        // Note：从打印的结果可以看出，虽然在父子容器中都定义了 user1，但最终取的是子容器中的 user1
        AnnotationConfigApplicationContext hierarchicalBeanFactory = getHierarchicalBeanFactory();
        Map<String, User> beanMap = BeanFactoryUtils.beansOfTypeIncludingAncestors(hierarchicalBeanFactory, User.class);
        beanMap.forEach((beanName, bean) -> {
            System.out.println(beanName + "->" + bean);
        });
    }

    /*-------------------------层次性查找：根据 Bean 名称查找-------------------------*/

    public static void findByName() {
        AnnotationConfigApplicationContext hierarchicalBeanFactory = getHierarchicalBeanFactory();
        System.out.println("容器中是否存在 user1：" + containsBean(hierarchicalBeanFactory, "user1"));
        System.out.println("容器中是否存在 user2：" + containsBean(hierarchicalBeanFactory, "user2"));
        System.out.println("容器中是否存在 user4：" + containsBean(hierarchicalBeanFactory, "user4"));
    }

    /**
     * 以双亲委派的方式查找 Bean
     *
     * @param localBeanFactory -
     * @param beanName         -
     * @return -
     */
    public static boolean containsBean(BeanFactory localBeanFactory, String beanName) {
        if (localBeanFactory == null) {
            return false;
        }

        // 如果存在父容器，则先到父容器查找
        if (localBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory localHierarchicalBeanFactory = (HierarchicalBeanFactory) localBeanFactory;
            BeanFactory parentBeanFactory = localHierarchicalBeanFactory.getParentBeanFactory();
            if (containsBean(parentBeanFactory, beanName)) {
                return true;
            }
        }

        // 如果不存在父容器，或父容器中找不到，则在当前容器查找
        boolean localBeanFactoryFindResult = localBeanFactory.containsBean(beanName);
        if (localBeanFactoryFindResult) {
            System.out.println("在 [" + localBeanFactory + "] 找到指定 " + beanName);
        }
        return localBeanFactoryFindResult;
    }

    /*-------------------------Supporter-------------------------*/

    public static AnnotationConfigApplicationContext getHierarchicalBeanFactory() {
        System.out.println("开始创建父容器...");
        AnnotationConfigApplicationContext parentBeanFactory = new AnnotationConfigApplicationContext(ParentBeanFactoryConfig.class);
        parentBeanFactory.setDisplayName("parentBeanFactory");
        System.out.println("父容器创建完成...\n");

        System.out.println("开始创建子容器...");
        AnnotationConfigApplicationContext childBeanFactory = new AnnotationConfigApplicationContext(ChildBeanFactoryConfig.class);
        childBeanFactory.setDisplayName("childBeanFactory");
        System.out.println("子容器创建完成...\n");

        childBeanFactory.setParent(parentBeanFactory);
        return childBeanFactory;
    }
}
